#include <jni.h>
#include <string>
#include <android/bitmap.h>
#include "gif_lib.h"
#include "malloc.h"
#include "android/log.h"

#define LOG_ATG "FRANK"
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_ATG,__VA_ARGS__);
#define  argb(a, r, g, b) ( ((a) & 0xff) << 24 ) | ( ((b) & 0xff) << 16 ) | ( ((g) & 0xff) << 8 ) | ((r) & 0xff)
typedef struct GifBean {
    //当前的帧数
    int current_frame;
    //总帧数
    int total_frame;
    //下一帧的播放时长
    int *dealys;
} GifBean;
extern "C" {


JNIEXPORT jlong JNICALL
Java_com_frankghost_le_playgif_GifHandler_loadGif(JNIEnv *env, jobject instance, jstring gifPath_) {
    const char *gifPath = env->GetStringUTFChars(gifPath_, 0);
    int err;
    GifFileType *gifFileType = DGifOpenFileName(gifPath, &err);
    //初始化结构体变量
    DGifSlurp(gifFileType);
    //申请内存
    GifBean *gifBean = (GifBean *) malloc(sizeof(GifBean));
    //清空内存地址
    memset(gifBean, 0, sizeof(GifBean));
    gifFileType->UserData = gifBean;
    //获取下一帧的播放时长
    gifBean->dealys = (int *) malloc(sizeof(int) * gifFileType->ImageCount);
    //初始化
    memset(gifBean->dealys, 0, sizeof(int) * gifFileType->ImageCount);
    gifBean->total_frame = gifFileType->ImageCount;
    ExtensionBlock *ext;
    for (int i = 0; i < gifFileType->ImageCount; ++i) {
        SavedImage frame = gifFileType->SavedImages[i];
        for (int j = 0; j < frame.ExtensionBlockCount; ++j) {
            //图形控制扩展块
            if (frame.ExtensionBlocks[j].Function == GRAPHICS_EXT_FUNC_CODE) {
                ext = &frame.ExtensionBlocks[j];
                break;
            }
        }
        if (ext) {
            //高八位向左偏移8个字节与低八位
            int frame_delay = 10 * (ext->Bytes[2] << 8 | ext->Bytes[1]);
            LOGE("时间frame_delay= %d", frame_delay);
            gifBean->dealys[i] = frame_delay;
        }
    }
    LOGE("gif 长度大小 %d", gifFileType->ImageCount);
    env->ReleaseStringUTFChars(gifPath_, gifPath);
    return (jlong) gifFileType;
}


jstring
Java_com_frankghost_le_playgif_MainActivity_stringFromJNI(
        JNIEnv *env,
        jobject /* this */) {
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}

JNIEXPORT jint JNICALL
Java_com_frankghost_le_playgif_GifHandler_gitHeight(JNIEnv *env, jobject instance, jlong gifPoint) {
    GifFileType *gifFileType = (GifFileType *) gifPoint;
    return gifFileType->SHeight;
}

JNIEXPORT jint JNICALL
Java_com_frankghost_le_playgif_GifHandler_gifWidth(JNIEnv *env, jobject instance, jlong gifPoint) {
    GifFileType *gifFileType = (GifFileType *) gifPoint;
    return gifFileType->SWidth;
}

//绘制一张图片
void drawFrame(GifFileType *gifFileType, GifBean *gifBean, AndroidBitmapInfo info, void *pixels) {
    //播放底层代码
    //拿到当前帧
    SavedImage savedImage = gifFileType->SavedImages[gifBean->current_frame];
    GifImageDesc desc = savedImage.ImageDesc;
    //整幅图片的首地址
    int *px = (int *) pixels;
    //每一行的首地址
    int *line;
    //其中一个像素的位置 不是指针    在颜色表中索引
    int pointPixels;
    GifByteType gifByteType;
    GifColorType gifColorType;
    ColorMapObject *colorMapObject = desc.ColorMap;
    px = (int *) ((char *) px + info.stride * desc.Top);
    for (int i = desc.Top; i < (desc.Top + desc.Height); ++i) {//行数
        line = px;
        for (int j = desc.Left; j < (desc.Left + desc.Width); ++j) {//列数
            pointPixels = (i - desc.Top) * desc.Width + (j - desc.Left);
            gifByteType = savedImage.RasterBits[pointPixels];
            gifColorType = colorMapObject->Colors[gifByteType];
            line[j] = argb(255, gifColorType.Red, gifColorType.Green, gifColorType.Blue);
        }
        px = (int *) ((char *) px + info.stride);
    }

}

JNIEXPORT jint JNICALL
Java_com_frankghost_le_playgif_GifHandler_updateFrame(JNIEnv *env, jobject instance, jobject bitmap,
                                                      jlong gifPoint) {
    //强转代表gif图片的结构体
    GifFileType *gifFileType = (GifFileType *) gifPoint;
    GifBean *gifBean = (GifBean *) gifFileType->UserData;
    AndroidBitmapInfo info;
    //代表一副图片的像素数组
    void *pixels;
    AndroidBitmap_getInfo(env, bitmap, &info);
    //锁定Bitmap  一副图片--->二维数组    一个二维数组
    AndroidBitmap_lockPixels(env, bitmap, &pixels);
    //TODO
    drawFrame(gifFileType, gifBean, info, pixels);
    //播放完成后 循环到下一帧
    gifBean->current_frame += 1;
    LOGE("当前帧 %d ", gifBean->current_frame);
    //当到最后一帧时,重新开始
    if (gifBean->current_frame >= gifBean->total_frame - 1) {
        gifBean->current_frame = 0;
        LOGE("重新开始 %d,总帧数： %d", gifBean->current_frame, gifBean->total_frame);
    }
    //解锁画布
    AndroidBitmap_unlockPixels(env, bitmap);
    //返回下一帧时长
    return gifBean->dealys[gifBean->current_frame];
}
}